<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #canvas{
            width:800px;
            height:800px;
            background-color:#ccc;
        }
    </style>
</head>
<body>
<canvas id = "canvas" width = "800" height = "800"></canvas>
<script>
    /*
    * canvas:画布，本质其实就是一个图片，可以动的图片，可以做游戏等复杂的特效
    *
    * canvas出现的原因：dom中有很多元素，需要相互渲染，当元素到达一定量级，就会变得卡顿，而使用canvas画出来可以解决渲染的性能问题
    *
    * canvas是es6新出的一个标签，标签里面包罗万象
    * canvas是一个行内元素inline
    *
    * 因为canvas是一个图片，所以它也有图片的属性，和图片四要素一样，width  height 和 alt 都应该在canvas行内设置好实际样式的宽高
    *
    * canvas获取到之后，需要再获取绘制环境和绘制工具 context
    *   使用 canvas.getContext("2d") 获取2d绘制环境
    *
    * 注意：如果是不同的绘制，需要在每次开始绘制前加上ctx.beginPath()，并在完成绘制后的末尾添加上ctx.closePath()，
    *      前者表示这次绘制路径开始，后者表示这次绘制路径结束，这样才能使得不同的绘制之间不相互影响
    * canvas的任何绘制都分成两步：
    *   1.描述绘制路径，只是在描述一个蓝图
    *   2.描述绘制方法，才真正在页面绘制出来
    *       绘制方法分为两种：一是描边stroke 二是填充fill
    *
    * */

    let canvas = document.querySelector("#canvas")

    let ctx = canvas.getContext("2d") //在canvas获取绘制环境和绘制工具context，现阶段使用2d平面即可

    /*
    * canvas的坐标和以前学过的知识一样：x水平向右为正方向，y垂直向下为正方向
    *
    * 画矩形
    *   rect(x,y,w,h)
    *       矩形的位置
    *       矩形的宽高
    *   rect接收四个参数：位置坐标x 位置坐标y 宽度w 高度h，即先规定一个起始位置坐标点，然后向左向下开始画图
    *
    * 画线
    *   moveTo(x,y) //移动画笔到初始位置
    *   lineTo(x,y) //连线到结束位置
    *
    * 画圆
    *   arc(x,y,r,0,Math.PI*2，false)
    *   接收的参数圆心x，y坐标，半径r，起始点角度0度，结束点角度360度，绘制方向默认false顺时针
    *
    * */

    ctx.beginPath() //开始这次绘制路径 每次绘制一个新的内容的时候都需要在绘制之前添加beginPath，这样才不会影响其他绘制或被其他绘制影响

    //描述绘制路径
    ctx.rect(100,100,50,100)

    ctx.strokeStyle = "red" //设置线条颜色
    ctx.fillStyle = "red" //设置填充颜色
    ctx.lineWidth = 3 //设置线条粗细

    //绘制
    ctx.stroke()
    ctx.fill()

    ctx.closePath() //结束这次绘制路径


    ctx.beginPath() //开始这次绘制
    ctx.rect(230,120,90,80)
    ctx.strokeStyle = "yellow"
    ctx.lineWidth = 6
    ctx.stroke()
    ctx.closePath() //结束此次绘制

    ctx.beginPath()
    ctx.strokeStyle = "green"
    ctx.lineWidth = 2
    ctx.moveTo(256,369)
    ctx.lineTo(542,412)
    ctx.stroke()
    ctx.closePath()

    /*
    * 用四条线连接成一个菱形，中心位置在400，400的点的位置，并且每个顶点距离中心位置的长度是150
    * */

    //ctx.beginPath()
    //ctx.moveTo(550,400)
    //ctx.lineTo(400,250)
    //ctx.lineTo(250,400)
    //ctx.lineTo(400,550)
    //ctx.lineTo(550,400) //最后别忘了连线回初始点位置形成封闭图形
    //ctx.stroke()
    //ctx.closePath()

    /*
    * 做一个函数，draw函数，接收一个参数n，表示绘制正n边形，
    * 中心的在400,400点的位置，每个顶点距离中心点位置距离长度为150
    *
    * 需要用到三角函数的知识：
    *   三角函数描述的是角度和边长的比值关系
    *   圆的圆周等于 2 * Math.PI * r
    *   相邻两条边的夹角度数为：2 * Math.PI / n
    *   设对边为a，对边所对的角为A，邻边为b，邻边所对的角为B，斜边为c，斜边所对的角为C
    *   则
    *   Math.sin(A) = a / c
    *   Math.cos(A) = b / c
    *   Math.tan(A) = a / b
    *
    *
    * */

    function draw(n,x,y,r){ //n表示正n边形，x表示该图形中心坐标x，y表示该图形中心坐标y，r表示各顶点到中心点距离
        //第一步应该先求出每个点坐标的（x，y）
        /*
        let point1 = {
            x:400 + 150 * Math.cos(Math.PI * 2 * 0 / n),
            y:400 - 150 * Math.cos(Math.PI * 2 * 0 / n)
        }
        let point2 = {
            x:400 + 150 * Math.cos(Math.PI * 2 * 1 / n),
            y:400 - 150 * Math.cos(Math.PI * 2 * 1 / n)
        }
        let point3 = {
            x:400 + 150 * Math.cos(Math.PI * 2 * 2 / n),
            y:400 - 150 * Math.cos(Math.PI * 2 * 2 / n)
        }
        let point4 = {
            x:400 + 150 * Math.cos(Math.PI * 2 * 3 / n),
            y:400 - 150 * Math.cos(Math.PI * 2 * 3 / n)
        }*/

        canvas.getContext("2d").beginPath()
        for(let i = 0;i <= n;i++){ //i小于等于n是为了最后连上初始点形成封闭图形
            let point = {
                x:x + r * Math.cos(Math.PI * 2 * i / n),
                y:y - r * Math.sin(Math.PI * 2 * i / n)
            }
            canvas.getContext("2d").lineTo(point.x,point.y)
        }
        canvas.getContext("2d").stroke()
        canvas.getContext("2d").closePath()
    }

    //绘制圆
    ctx.beginPath()
    ctx.arc(200,500,100,0,Math.PI*2)
    ctx.fill()
    ctx.stroke()
    ctx.closePath()

    //绘制扇形
    ctx.beginPath()
    ctx.arc(300,600,100,0,Math.PI/2)
    ctx.lineTo(300,600) //连线到圆心
    ctx.lineTo(400,600) //连线到起始点
    ctx.stroke()
    ctx.fill()
    ctx.closePath()

    //绘制图片
    let img = new Image()
    img.src = "./imgs/01.jpg"

    //等待图片加载好才能绘制
    img.onload = function (){
        ctx.drawImage(img,100,100) //接收图片img，图片左顶点x，y坐标
    }

    //也可以用异步代码绘制图片
    new Promise(function (resolve){
        let img = new Image()
        img.src = "./imgs/01.jpg"
        img.onload = function (){
            resolve(img)
        }
    })
    .then(//(img) => {
        //ctx.drawImage(img,100,100)
    //}
        drawImage
    )

    function drawImage(img){ //这里只是将原来then操作中的回调函数封装了出来
        ctx.drawImage(img,100,100)
    }

    //异步代码绘制图片进一步封装
    function loadImg(src){ //加载图片
        return new Promise(function (resolve){
            //Image是一个构造函数，实例化一个可以添加src的图片对象
            let img = new Image()
            img.src = src
            img.onload = function (){
                resolve(img)
            }
        })
    }

    loadImg("./imgs/01.jpg")
        .then(//(img) => {
            //ctx.drawImage(img,100,100)
            //}
            drawImage //绘制图片
        )
    function drawImage(img){ //这里只是将原来then操作中的回调函数封装了出来
        ctx.drawImage(img,100,100)
    }

    /*
    * 绘制图片
    *
    * 1 .drawImage() 接收三个参数的情况
    *   .drawImage(img,x,y)
    *   img对象
    *   x,y 表示绘制图片的左上角顶点坐标
    *   例如：ctx.drawImage(img,100,100)
    *
    * 2 .drawImage() 接收五个参数的情况
    *   .drawImage(img,x,y,w,h)
    *   img对象
    *   x,y 表示绘制图片的左上角顶点坐标
    *   w,h 表示绘制图片的宽高
    *   例如：
    *   let height = img.height / img.width * 500 //这里是为了防止图片变形，宽为500时等比例压缩图片的高
    *   ctx.drawImage(img,100,100,500,height) //所以最后这个参数直接将上面的height传进去
    *
    * 3 .drawImage() 接收九个参数的情况：从原始图片中裁剪一个矩形区域下来在页面中显示
    *   img对象
    *   x,y 表示原始图片的裁剪开始位置
    *   w,h 表示元素图片的裁剪宽高
    *
    *   x,y 表示图片开始绘制的左上角坐标
    *   w,h 表示图片绘制的宽高
    *   例如：
    *   ctx.drawImage(img,500,500,900,900,100,100,600,600)
    *   //从原始图片img对象上，从原始图片的（500，500）坐标开始，裁剪宽900，高900的图片区域，在canvas标签内，从（100,100）坐标开始，
    *   //绘制宽600，高600的图片
    *
    *
    * */

</script>
</body>
</html>